import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.*;

public class EmailUtil {
    private final static String default_charset = "UTF-8";

    public static enum EncryptionTypes {
        Default, TLS, SSL
    }

    static final Log logger = LogFactory.getLog(EmailUtil.class);
    private String mail_host = "";
    private int mail_port = 25;
    private int encryptionType = EncryptionTypes.Default.ordinal();
    private boolean auth = false;
    private String mail_host_account = "";
    private String mail_host_password = "";
    private boolean isHtml = true;

    public EmailUtil(String mail_host) {
        this.mail_host = mail_host;
    }

    public EmailUtil(String mail_host, boolean auth, String account, String password) {
        this(mail_host, 25, EncryptionTypes.Default.ordinal(), auth, account, password);
    }

    public EmailUtil(String mail_host, int mail_port, int encryptionType, boolean auth, String account, String password) {
        this.mail_host = mail_host;
        this.mail_port = mail_port;
        this.encryptionType = encryptionType;
        this.auth = auth;
        this.mail_host_account = account;
        this.mail_host_password = password;
    }

    public EmailUtil(String mail_host, boolean auth, String account, String password, boolean isHtml) {
        this(mail_host, 25, EncryptionTypes.Default.ordinal(), auth, account, password, isHtml);
    }

    public EmailUtil(String mail_host, int mail_port, int encryptionType, boolean auth, String account, String password, boolean isHtml) {
        this.mail_host = mail_host;
        this.mail_port = mail_port;
        this.encryptionType = encryptionType;
        this.auth = auth;
        this.mail_host_account = account;
        this.mail_host_password = password;
        this.isHtml = isHtml;
    }

    public void sendEmail(String senderAddress, String senderName, String receiverAddress, String sub, String msg) throws Exception {
        String[] address = receiverAddress.split(";");
        List recipients = new ArrayList();
        for (int i = 0; i < address.length; i++) {
            if (address[i].trim().length() > 0) {
                recipients.add(address[i]);
            }
        }
        this.sendEmail(senderAddress, senderName, recipients, sub, msg);
    }

    public void sendEmail(String senderAddress, String senderName, List recipients, String sub, String msg) throws SendFailedException {
        this.sendEmail(senderAddress, senderName, recipients, sub, msg, null);
    }

    public void sendEmail(String senderAddress, String senderName, String receiverAddress, String sub, String msg, Collection attachments) throws Exception {
        String[] address = receiverAddress.split(";");
        List recipients = new ArrayList();
        for (int i = 0; i < address.length; i++) {
            if (address[i].trim().length() > 0) {
                recipients.add(address[i]);
            }
        }
        this.sendEmail(senderAddress, senderName, recipients, sub, msg, attachments);
    }

    public void sendEmailByProxy(String proxyHost, String proxyPort, String senderAddress, String senderName, String receiverAddress, String sub, String msg, Collection attachments) throws Exception {
        String[] address = receiverAddress.split(";");
        List recipients = new ArrayList();
        for (int i = 0; i < address.length; i++) {
            if (address[i].trim().length() > 0) {
                recipients.add(address[i]);
            }
        }
        this.sendEmailByProxy(proxyHost, proxyPort, senderAddress, senderName, recipients, sub, msg, attachments);
    }

    public void sendEmail(String senderAddress, String senderName, List recipients, String sub, String msg, Collection attachments) throws SendFailedException {
        Transport transport = null;
        try {
            Properties props = this.getProperties();
            Session session = this.getSession(props);
            MimeMessage message = new MimeMessage(session);
            if (this.getDefaultIsHtml()) {
                message.addHeader("Content-type", "text/html");
            } else {
                message.addHeader("Content-type", "text/plain");
            }
            message.setSubject(sub, default_charset);
            message.setFrom(new InternetAddress(senderAddress, senderName));
            for (Iterator it = recipients.iterator(); it.hasNext();) {
                String email = (String) it.next();
                message.addRecipients(Message.RecipientType.TO, email);
            }
            Multipart mp = new MimeMultipart();
            MimeBodyPart contentPart = new MimeBodyPart();
            if (this.getDefaultIsHtml()) {
                contentPart.setContent("<meta http-equiv=Content-Type content=text/html; charset=" + default_charset + ">" + msg, "text/html;charset=" + default_charset);
            } else {
                contentPart.setText(msg, default_charset);
            }
            mp.addBodyPart(contentPart);
            if (attachments != null) {
                MimeBodyPart attachPart;
                for (Iterator it = attachments.iterator(); it.hasNext();) {
                    attachPart = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(it.next().toString().trim());
                    attachPart.setDataHandler(new DataHandler(fds));
                    if (fds.getName().indexOf("$") != -1) {
                        attachPart.setFileName(fds.getName().substring(fds.getName().indexOf("$") + 1, fds.getName().length()));
                    } else {
                        attachPart.setFileName(fds.getName());
                    }
                    mp.addBodyPart(attachPart);
                }
            }
            message.setContent(mp);
            message.setSentDate(new Date());
            if (this.getDefaultEncryptionType() == EncryptionTypes.SSL.ordinal()) {
                Transport.send(message);
            } else {
                transport = session.getTransport("smtp");
                transport.connect(this.mail_host, this.mail_port, this.mail_host_account, this.mail_host_password);
                transport.sendMessage(message, message.getAllRecipients());
            }
        } catch (Exception e) {
            logger.error("send mail error", e);
            throw new SendFailedException(e.toString());
        } finally {
            if (transport != null) {
                try {
                    transport.close();
                } catch (Exception ex) {
                }
            }
        }
    }

    public void sendEmailByProxy(String proxyHost, String proxyPort, String senderAddress, String senderName, List recipients, String sub, String msg, Collection attachments) throws SendFailedException {
        Transport transport = null;
        try {
            Properties props = this.getProxyProperties(proxyHost, proxyPort);
            Session session = this.getSession(props);
            MimeMessage message = new MimeMessage(session);
            if (this.getDefaultIsHtml()) {
                message.addHeader("Content-type", "text/html");
            } else {
                message.addHeader("Content-type", "text/plain");
            }
            message.setSubject(sub, default_charset);
            message.setFrom(new InternetAddress(senderAddress, senderName));
            for (Iterator it = recipients.iterator(); it.hasNext();) {
                String email = (String) it.next();
                message.addRecipients(Message.RecipientType.TO, email);
            }
            Multipart mp = new MimeMultipart();
            MimeBodyPart contentPart = new MimeBodyPart();
            if (this.getDefaultIsHtml()) {
                contentPart.setContent("<meta http-equiv=Content-Type content=text/html; charset=" + default_charset + ">" + msg, "text/html;charset=" + default_charset);
            } else {
                contentPart.setText(msg, default_charset);
            }
            mp.addBodyPart(contentPart);
            if (attachments != null) {
                MimeBodyPart attachPart;
                for (Iterator it = attachments.iterator(); it.hasNext();) {
                    attachPart = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(it.next().toString().trim());
                    attachPart.setDataHandler(new DataHandler(fds));
                    if (fds.getName().indexOf("$") != -1) {
                        attachPart.setFileName(fds.getName().substring(fds.getName().indexOf("$") + 1, fds.getName().length()));
                    } else {
                        attachPart.setFileName(fds.getName());
                    }
                    mp.addBodyPart(attachPart);
                }
            }
            message.setContent(mp);
            message.setSentDate(new Date());
            if (this.getDefaultEncryptionType() == EncryptionTypes.SSL.ordinal()) {
                Transport.send(message);
            } else {
                transport = session.getTransport("smtp");
                transport.connect(this.mail_host, this.mail_port, this.mail_host_account, this.mail_host_password);
                transport.sendMessage(message, message.getAllRecipients());
            }
        } catch (Exception e) {
            logger.error("send mail error", e);
            throw new SendFailedException(e.toString());
        } finally {
            if (transport != null) {
                try {
                    transport.close();
                } catch (Exception ex) {
                }
            }
        }
    }

    private Properties getProperties() {
        Properties props = System.getProperties();
        int defaultEncryptionType = this.getDefaultEncryptionType();
        if (defaultEncryptionType == EncryptionTypes.TLS.ordinal()) {
            props.put("mail.smtp.auth", String.valueOf(this.auth));
            props.put("mail.smtp.starttls.enable", "true");
        } else if (defaultEncryptionType == EncryptionTypes.SSL.ordinal()) {
            props.put("mail.smtp.host", this.mail_host);
            props.put("mail.smtp.socketFactory.port", this.mail_port);
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.debug", "true");
            props.put("mail.smtp.auth", String.valueOf(this.auth));
            props.put("mail.smtp.port", this.mail_port);
        } else {
            props.put("mail.smtp.host", this.mail_host);
            props.put("mail.smtp.auth", String.valueOf(this.auth));
        }
        return props;
    }

    // 设置代理服务器  
    private Properties getProxyProperties(String proxyHost, String proxyPort) {
        Properties props = System.getProperties();
        props.setProperty("proxySet", "true");
        props.setProperty("socksProxyHost", proxyHost);
        props.setProperty("socksProxyPort", proxyPort);
        props.setProperty("mail.smtp.host", this.mail_host);
        props.put("mail.smtp.auth", String.valueOf(this.auth));
        props.put("mail.debug", "true");
        return props;
    }

    private Session getSession(Properties props) {
        Session session = null;
        if (this.getDefaultEncryptionType() == EncryptionTypes.TLS.ordinal()) {
            session = Session.getInstance(props);
        } else if (this.getDefaultEncryptionType() == EncryptionTypes.SSL.ordinal()) {
            session = Session.getInstance(props, new MyAuthenticator(this.mail_host_account, this.mail_host_password));
        } else {
            session = Session.getDefaultInstance(props, null);
        }
        return session;
    }

    private boolean getDefaultIsHtml() {
        boolean rst = this.isHtml;
        return rst;
    }

    private class MyAuthenticator extends Authenticator {
        String user;
        String password;

        public MyAuthenticator() {
        }

        public MyAuthenticator(String user, String password) {
            this.user = user;
            this.password = password;
        }

        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(this.user, this.password);
        }
    }

    private int getDefaultEncryptionType() {
        int rst = this.encryptionType;
        if (this.encryptionType == EncryptionTypes.Default.ordinal()) {
            if (this.mail_port == 465) {
                rst = EncryptionTypes.SSL.ordinal();
            } else if (this.mail_port == 587) {
                rst = EncryptionTypes.TLS.ordinal();
            }
        }
        return rst;
    }

    public static void main(String[] args) throws Exception {
        EmailUtil email = new EmailUtil("smtp.126.com", 25, 0, true, "cainiaotian@126.com", "631344", true);
        Collection col = new ArrayList();
        try {
            StringBuffer sb = new StringBuffer();
            sb.append("<html><head></head><body>");
            sb.append("<p><span style=\"font-size:16px; color:#009900 ;font: bold;\">亲爱的用户：test</span></p>");
            sb.append("<p>点击以下链接完成注册：</p>");
            sb.append("<p></p>");
            sb.append("<p>如果你的邮箱不支持链接点击，请将以上链接地址拷贝到你的浏览器地址栏中。</p>");
            sb.append("<p>此邮件由系统自动产生，请勿回复。(该链接仅在7日内点击有效，如果超过7日未点击确认，请你登录菩提蛮，并申请重发激活邮件)。</p>");
            sb.append("</body></html>");
            email.sendEmailByProxy("122.226.7.210", "80", "cainiaotian@126.com", "标题", "cainiaotian@126.com", "欢迎注册", sb.toString(), col);
            System.out.println("发送成功！");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("发送失败！");
        }
    }
}